package programs.statement;

import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Set;

import game.SpaceObject;
import programs.ProgramFactory.ForeachType;
import programs.expression.implementedClasses.Variable;
import programs.kind.ForEachType;

public class ForEachLoop extends Loop {

	private final ForEachType kind;
	private Variable variable;
	
	public ForEachLoop(Statement loopStatement, ForeachType type, Variable variable) {
		super(loopStatement);
		if(type == ForeachType.ANY)
			this.kind = new programs.kind.Any();
		else if(type == ForeachType.ASTEROID)
			this.kind = new programs.kind.Asteroid();
		else if(type == ForeachType.BULLET)
			this.kind = new programs.kind.Bullet();
		else if(type == ForeachType.SHIP)
			this.kind = new programs.kind.Ship();
		else
			this.kind = null;
		this.variable = variable;
	}
	
	@Override
	public boolean isValidStatement() {
		
//		if(! getKind().hasNext())
//			return getKind().getReturnType() == getVariable().getReturnType() && (! getLoopStatement().containsAction());
		if(getVariable().getValue() != null)
			return super.isValidStatement() && getKind().getReturnType() == getVariable().getReturnType() && (! getLoopStatement().containsAction());
		else {
			getVariable().setValue(new game.Ship());
			if(super.isValidStatement() && getKind().getReturnType() == getVariable().getReturnType() && (! getLoopStatement().containsAction())) {
				getVariable().setValue(null);
				return true;
			}
			return false;
		}
			
	}
	
	public ForEachType getKind() {
		return this.kind;
	}
	
	public Variable getVariable() {
		return this.variable;
	}

	@Override
	public void setExecuter(game.Ship executer) {
		super.setExecuter(executer);
	}
	
	@Override
	public void assignGlobalVariable(Variable variable) {
		super.assignGlobalVariable(variable);
		this.variable = (this.variable).assignGlobalVariable(variable);
	}
	
	@Override
	public Set<Variable> getVariables(){
		Set<Variable> set = super.getVariables();
		set.add(getVariable());
		return set;
	}
	
	@Override
	public Iterator<BasicStatement> getIterator() {
		return new Iterator<BasicStatement>()  {

		private Iterator<BasicStatement> currentIterator = getLoopStatement().getIterator();
		private Iterator<SpaceObject> objectIterator = getKind().getIterator(getExecuter());
		{
			if(objectIterator.hasNext())
				getVariable().setValue(objectIterator.next());
		}
	
		public boolean hasNext() {
			if(currentIterator.hasNext())
				return true;
			if(!getLoopStatement().isEmpty() && objectIterator.hasNext())
				return true;
			return false;
		}

		public BasicStatement next() throws NoSuchElementException {
			if(!hasNext())
				throw new NoSuchElementException();
			if(currentIterator.hasNext())
				return currentIterator.next();
			else {
				getVariable().setValue(objectIterator.next());
				currentIterator = getLoopStatement().getIterator();
				return currentIterator.next();
			}
		}

		public void remove() throws UnsupportedOperationException {
			throw new UnsupportedOperationException();
		}
		};
	}
}
